﻿using System;
using Microsoft.Xna.Framework;
using Stonecode.Solar.ParticleEngine.ParticleSystems;
using Stonecode.Solar.ParticleEngine.Utils;
using Microsoft.Xna.Framework.Graphics;


namespace Stonecode.Solar.ParticleEngine.Emitters
{
    public class LineEmitter : Emitter
    {
        //private float HalfLength;
        //private float _rotation;
        
        //private Matrix mRot;
        //private Matrix mRot90;
        

        //public bool UsePerpendicularVelocity = true;
        //public Vector3 Position;

        public LineEmitterTypeSettings EmitterTypeSettings { get; set; }

        //public float Length 
        //{ 
        //    get { return HalfLength * 2f; } 
        //    set { HalfLength = value * 0.5f; } 
        //}

        //public float Rotation
        //{
        //    get { return EmitterTypeSettings.Rotation; }
        //    set
        //    {
        //        //_rotation = value;
        //        EmitterTypeSettings.Rotation = value;
        //        mRot = Matrix.CreateRotationZ(value);
        //    }
        //}
        
        public LineEmitter(GraphicsDevice graphics, Effect pEffect, EmitterSettings psettings,
            Texture2D texture, float particlesPerSecond, Vector3 pos, float lLength, float rot,
            Matrix view, Matrix proj)
        : base(graphics, pEffect, psettings, texture, particlesPerSecond, view, proj, EmitterType.Line)
        {
            EmitterTypeSettings = new LineEmitterTypeSettings(lLength, rot, true);
            Position = pos;
            //Rotation = rot;
        }

        public override void Dispose()
        {
            EmitterTypeSettings = null;
            base.Dispose();
        }

        public void GetPointOnLine(out Vector3 p, out Vector2 v)
        {
            Vector2 pos = Vector2.Zero; 
            v = Vector2.Zero;
            
            // Get a random point within the line. We will rotate it later
            NumberGenerator.GenerateRandomFloat(-EmitterTypeSettings.HalfLength, +EmitterTypeSettings.HalfLength, out pos.X);
            
            
            
            // Transform the point by the rotation value
            Vector2.Transform(ref pos, ref EmitterTypeSettings.mRot, out pos);
            
            // Now return the output of the transformed position + our base position
            //pos += new Vector2(Position.X, Position.Y);
            p = new Vector3(pos.X + Position.X, pos.Y + Position.Y, Position.Z);
            

            // Create a vector with Y + 1 of where we are for Velocity control
            Vector2 vc = new Vector2(0, 1f);
            
            // Calculate Velocity

            if (EmitterTypeSettings.PerpendicularVelocity) // then velocity should stay true to rotation
            {
                float f;
                NumberGenerator.GenerateRandomFloat(_particleSystem.Settings.MinVerticalVelocity,
                    _particleSystem.Settings.MaxVerticalVelocity, out f);
                Vector2.Transform(ref vc, ref EmitterTypeSettings.mRot, out vc);
                v = vc * f;
                //vc = vc - pos;
                //v = vc - pos;
            }
            else // we don't care what direction the particle moves
            {
                NumberGenerator.GenerateRandomFloat(_particleSystem.Settings.MinVerticalVelocity,
                    _particleSystem.Settings.MaxVerticalVelocity, out v.Y);
                NumberGenerator.GenerateRandomFloat(_particleSystem.Settings.MinHorizontalVelocity,
                    _particleSystem.Settings.MaxHorizontalVelocity, out v.X);
            }
            
        }


        public override void Update(float dt)
        {
            if (IsAlive && Enabled && AutoGenerate)
            {
                // Work out how much time has passed since the previous update.
                //float elapsedTime = dt; //(float)gameTime.ElapsedGameTime.TotalSeconds;

                if (dt > 0)
                {
                    // If we had any time left over that we didn't use during the
                    // previous update, add that to the current elapsed time.
                    float timeToSpend = timeLeftOver + dt;

                    // Counter for looping over the time interval.
                    float currentTime = -timeLeftOver;

                    // Create particles as long as we have a big enough time interval.
                    while (timeToSpend > timeBetweenParticles)
                    {
                        currentTime += timeBetweenParticles;
                        timeToSpend -= timeBetweenParticles;

                        Vector3 position;
                        Vector2 velocity;
                        GetPointOnLine(out position, out velocity);
                        //GetPointOnLine();

                        // Create the particle.
                        _particleSystem.AddParticleManualVelocity(position, new Vector3(velocity, 0));
                    }

                    // Store any time we didn't use, so it can be part of the next update.
                    timeLeftOver = timeToSpend;
                }
            }

            
            base.Update(dt);
        }

        public override void Trigger(float dt)
        {
            float timeToSpend = timeLeftOver + dt;

            // Counter for looping over the time interval.
            float currentTime = -timeLeftOver;

            // Create particles as long as we have a big enough time interval.
            while (timeToSpend > timeBetweenParticles)
            {
                currentTime += timeBetweenParticles;
                timeToSpend -= timeBetweenParticles;
                Vector3 position;
                Vector2 velocity;
                GetPointOnLine(out position, out velocity);
                //GetPointOnLine();

                // Create the particle.
                _particleSystem.AddParticleManualVelocity(position, new Vector3(velocity, 0));
            }
            timeLeftOver = timeToSpend;
        }

        public override void Trigger(int particleCount)
        {
            Vector3 position;
            Vector2 velocity;

            for (int i = 0; i < particleCount; i++)
            {
                GetPointOnLine(out position, out velocity);
                //GetPointOnLine();

                // Create the particle.
                _particleSystem.AddParticleManualVelocity(position, new Vector3(velocity, 0));
            }
        }

        public override void TriggerWithOffset(float dt, Vector2 offset)
        {
            float timeToSpend = timeLeftOver + dt;

            // Counter for looping over the time interval.
            float currentTime = -timeLeftOver;

            // Create particles as long as we have a big enough time interval.
            while (timeToSpend > timeBetweenParticles)
            {
                currentTime += timeBetweenParticles;
                timeToSpend -= timeBetweenParticles;
                Vector3 position;
                Vector2 velocity;
                GetPointOnLine(out position, out velocity);
                position.X += offset.X;
                position.Y += offset.Y;
                //GetPointOnLine();

                // Create the particle.
                _particleSystem.AddParticleManualVelocity(position, new Vector3(velocity, 0));
            }
            timeLeftOver = timeToSpend;

        }
    }
}
